package math;

import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
import org.apache.commons.math3.analysis.differentiation.UnivariateDifferentiableFunction;
import org.apache.commons.math3.analysis.solvers.NewtonRaphsonSolver;
import org.apache.commons.math3.exception.DimensionMismatchException;


public class NewtonIterationExample {
    public static void main(String[] args) {

        // 创建牛顿迭代求解器
        NewtonRaphsonSolver solver = new NewtonRaphsonSolver(1e-6);

        // 设置求解器的初始猜测值和收敛条件
        double initialGuess = 0; // 初始猜测值
        int maxIterations = 100; // 最大迭代次数

        // 执行牛顿迭代计算
        UnivariateObjectiveFunction doFunc = new UnivariateObjectiveFunction(2,-2,-23);
        double result = solver.solve(
                maxIterations,
                doFunc,
                initialGuess
        );

        // 输出计算结果
        System.out.println("方程的解为:X= " + result);
        System.out.println("y="+doFunc.value(result));

    }
}

// 内部类，用于封装目标函数
class UnivariateObjectiveFunction implements UnivariateDifferentiableFunction {
    private double a;
    private double b;
    private double c;

    //构造函数传入相关参数
    public UnivariateObjectiveFunction(double a,double b, double c) {
        //根据实际函数调整
        this.a = a;
        this.b = b;
        this.c = c;
    }

    //函数实现，根据实际函数修改调整
    //测试函数 a * x * x + b * x + c = 0
    public double value(double x) {
        return this.a * x * x + this.b * x + this.c;
    }

    //导函数
    // fx = axx+bx+c
    // df = 2ax+b
    public DerivativeStructure value(DerivativeStructure t) throws DimensionMismatchException {
//        //定义自变量ds, 下面函数四个形参依次为 变量数，最高导数阶数， 变量位序(主要在多元函数求微分次序有关)变量值... 
//        这里值有两个和最高导数阶数有关这里导数阶数是1所以就有0阶导数（原函数）值，1阶导数值两个依次类推。
//        DerivativeStructure ds = new DerivativeStructure(1, 1, 0, t.getValue());
//        //构造函数f(x)
//        DerivativeStructure fx = ds.pow(2).multiply(this.a).add(ds.multiply(this.b)).add(this.c);
//        return fx;
        double x =  t.getValue();
        double y = this.value(x);
        double y0 = this.value(x+1E-10);
        double y1 = this.value(x-1E-10);
        double dy = (y0-y1)/(2*1E-10);
        DerivativeStructure ds = new DerivativeStructure(1, 1, y, dy);
        return ds;
    }
}

